﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;

namespace Watermark
{
    public class WaterMarkHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            HttpResponse Response = context.Response;
            HttpRequest Request = context.Request;

            Response.ContentType = "image/jpeg";
            string filePath = Request.FilePath;
            string physicalPath = context.Server.MapPath(filePath);

            if (!File.Exists(physicalPath))
                return;

            string url = context.Request.RawUrl.ToLower();
            if (!url.EndsWith(".jpg"))
            {
                return;
            }

            if (string.IsNullOrEmpty(physicalPath))
            {
                return;
            }

            string waterImagePath = context.Server.MapPath("/Images/watermark.png");
            IList<string> ruleList = new List<string>();
            IList<string> excludeList = new List<string>();
            string isOpen = string.Empty;
            int padding = 10;
            int pos = 6;
            int quality = 80;
            int transparency = 100;

            WaterMarkConfig waterConfig = WaterMarkConfig.GetInstance();
            if (waterConfig != null)
            {
                isOpen = waterConfig.isOpen;
                waterImagePath = context.Server.MapPath(waterConfig.filePath);
                ruleList = waterConfig.contain;
                excludeList = waterConfig.exclude;
                padding = waterConfig.padding;
                pos = waterConfig.pos;
                quality = waterConfig.quality;
                transparency = waterConfig.transparency;
            }


            bool doWaterMark = false;
            var filepath = filePath.ToLower();
            foreach (string _rule in ruleList)
            {
                if (filepath.Contains(_rule))
                {
                    doWaterMark = true;
                    break;
                }
            }

            if (doWaterMark && excludeList.Any(o => filepath.Contains(o)))
            {
                doWaterMark = false;
            }

            Image cover = Image.FromFile(context.Request.PhysicalPath);
            if (isOpen.Equals("1") && doWaterMark)
            {
                //加载水印图片
                Image watermark = Image.FromFile(waterImagePath);
                AddImagWater(cover, watermark, pos, quality, transparency);
                watermark.Dispose();
            }

            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            ImageCodecInfo ici = null;
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.MimeType.IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) > -1)
                {
                    ici = codec;
                }
            }
            EncoderParameters encoderParams = new EncoderParameters();
            long[] qualityParam = new long[1];
            if (quality < 0 || quality > 100)
            {
                quality = 80;
            }
            qualityParam[0] = quality;
            EncoderParameter encoderParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qualityParam);
            encoderParams.Param[0] = encoderParam;

            //设置输出类型图片为jpeg格式
            context.Response.ContentType = "image/jpeg";
            //将修改的图片存入输出流中
            if (ici != null)
            {
                cover.Save(context.Response.OutputStream, ici, encoderParams);
            }
            else
            {
                cover.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            cover.Dispose();
            context.Response.End();
        }

        /// <summary>
        /// 加图片水印
        /// </summary>
        /// <param name="path">要加水印的图片</param>
        /// <param name="filename">加好水印保存到哪</param>
        /// <param name="watermarkFilename">水印图</param>
        /// <param name="watermarkStatus">水印位置 0=不使用 1=左上 2=中上 3=右上 4=左中 ... 9=右下</param>
        /// <param name="quality">图片生成后的质量.0-100</param>
        /// <param name="watermarkTransparency">透明度,100为不透明</param>
        public static Image AddImagWater(Image img, Image watermark, int watermarkStatus, int quality, int watermarkTransparency)
        {
            Graphics g = Graphics.FromImage(img);
            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //设置高质量,低速度呈现平滑程度
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            if (watermark.Height >= img.Height || watermark.Width >= img.Width)
            {
                return img;
            }

            int xpos = 0;
            int ypos = 0;
            if (watermarkStatus < 10)
            {
                watermarkStatus = watermarkStatus * 10 + 5;
            }
            var big = watermarkStatus / 10;
            var small = watermarkStatus % 10;
            var w2 = (int)Math.Floor(img.Width / 3.0);
            var h2 = (int)Math.Floor(img.Height / 3.0);
            getWatermarkPos(img.Width, img.Height, w2, h2, big, ref xpos, ref ypos);
            var xxpos = 0;
            var yypos = 0;
            getWatermarkPos(w2, h2, watermark.Width, watermark.Height, small, ref xxpos, ref yypos);
            xpos += xxpos;
            ypos += yypos;

            float transparency = 0.5F;
            if (watermarkTransparency >= 1 && watermarkTransparency <= 100)
            {
                transparency = (watermarkTransparency / 100.0F);
            }
            ImageAttributes imageAttributes = GetImageAttributesInstance(transparency);
            g.DrawImage(watermark, new Rectangle(xpos, ypos, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, GraphicsUnit.Pixel, imageAttributes);
            //g.DrawImage(watermark, new System.Drawing.Rectangle(xpos, ypos, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, System.Drawing.GraphicsUnit.Pixel);

            g.Dispose();
            //img.Dispose();
            watermark.Dispose();
            //imageAttributes.Dispose();
            return img;
        }
        private static void getWatermarkPos(int width, int height, int waterWidth, int waterHeight, int pos, ref int xpos,
            ref int ypos)
        {
            var x = ((pos - 1) % 3) * 0.5;
            var y = Math.Floor((pos - 1) / 3.0) * 0.5;
            xpos = (int)(width * x + (-x) * waterWidth);
            ypos = (int)(height * y + (-y) * waterHeight);

        }/// <summary>
         /// Get image attribute instance.
         /// </summary>
         /// <param name="alpha">transparency value</param>
         /// <returns></returns>
        private static ImageAttributes GetImageAttributesInstance(float alpha)
        {
            // imageattributes instance which will control the related infomations for image.
            ImageAttributes imageAttributes = new ImageAttributes();

            // 图片映射：水印图被定义成拥有绿色背景色的图片被替换成透明 
            ColorMap colorMap = new ColorMap();
            colorMap.OldColor = Color.FromArgb(255, 0, 255, 0);
            colorMap.NewColor = Color.FromArgb(0, 0, 0, 0);
            imageAttributes.SetRemapTable(new ColorMap[] { colorMap }, ColorAdjustType.Bitmap);

            float[][] colorMatrixElements = new float[][]
            {
                new float[] {1.0f, 0.0f, 0.0f, 0.0f, 0.0f}, // red红色 
                new float[] {0.0f, 1.0f, 0.0f, 0.0f, 0.0f}, // green绿色 
                new float[] {0.0f, 0.0f, 1.0f, 0.0f, 0.0f}, // blue蓝色 
                new float[] {0.0f, 0.0f, 0.0f, alpha, 0.0f}, // 透明度 
                new float[] {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}
            };

            // ColorMatrix:定义包含 RGBA 空间坐标的 5 x 5 矩阵。 
            // ImageAttributes:类的若干方法通过使用颜色矩阵调整图像颜色。 
            imageAttributes.SetColorMatrix(new ColorMatrix(colorMatrixElements), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

            return imageAttributes;
        }

        public bool IsReusable
        {
            get { return false; }
        }
    }
}
